home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-27 | 8.3 KB | 383 lines | [TEXT/CWIE] |
- // =======================================================================
- // 3D Class Library, © Xilex Group
- // - ------------------------------------------------------------------- -
- // Written by Dmitry Boldyrev
- // =======================================================================
-
- #include <stdio.h>
- #include <string.h>
- #include <QDOffscreen.h>
- #include <profiler.h>
- #include "3dcl.h"
-
- Point middle;
-
- Ptr baseAddr;
- short rowBytes;
-
- UBYTE *thepic;
-
- typedef struct
- {
- unsigned char r:8, g:8, b:8;
- } color;
-
- color *pal;
-
- Rect rBounds;
-
- #define iHandCursor 200
- #define iNewHandCursor 201
-
- static void InitToolBox()
- {
- EventRecord event;
- short count;
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
- SetEventMask(everyEvent);
-
- for (count = 1; count <= 3; count++) {
- MoreMasters();
- EventAvail(everyEvent, &event);
- }
- FlushEvents(everyEvent, 0);
- }
-
- static void load_pic (void)
- {
- FILE *fp;
-
- thepic = new UBYTE[65535];
- pal = new color[256];
-
- fp = fopen ("o021.raw", "rb");
- fread (pal, 1, sizeof(color) * 256, fp); /* Load the palette */
- fread (thepic, 1, 65535, fp); /* Load the picture */
- fclose (fp);
- }
-
- static void delete_pic (void)
- {
- delete[] pal;
- delete[] thepic;
- }
-
- #define kDiffuse 24
- #define kSpecular (32 - kDiffuse)
-
- #define MAXCOL 64
-
- static unsigned char closest_match (int red, int green, int blue, color *pal)
- {
- int colnum; /* Color number to compare */
- int delta_r, delta_g, delta_b; /* Difference between new and existing */
- float distance; /* Distance from new color */
- float lowest_distance; /* Lowest distance found */
- int closest_color; /* Color with the lowest distance */
-
-
- lowest_distance = 33333;
- /* Set to a high number, higher than anything possible.
- The highest distance we can have is sqrt (64*64 + 64*64 + 64*64)
- which is 110.85 */
-
- for (colnum = 0; colnum < MAXCOL; colnum++)
- /* Compare each color from the existing palette */
- {
-
- delta_r = (pal[colnum].r - red);
- delta_g = (pal[colnum].g - green);
- delta_b = (pal[colnum].b - blue);
-
- distance = sqrt (delta_r*delta_r*30 + delta_g*delta_g*59 + delta_b*delta_b*11);
-
- if (distance < lowest_distance)
- {
- lowest_distance = distance;
- closest_color = colnum;
- }
- }
-
- return (closest_color);
- }
-
-
- static void create_fade_table (int frame, int maxframe,
- unsigned char *fadetable, color *pal)
- {
-
- float lightlevel1; /* Percentage of color 1 */
- float lightlevel2; /* Percentage of color 2 */
-
- float fr, fg, fb; /* Floating point RGB values of color 1 */
- float fr2, fg2, fb2; /* Floating point RGB values of color 2 */
- int ir, ig, ib; /* Integer RGB values after combing the two above */
-
- int col1, col2;
-
- unsigned char bestcolor; /* Best match */
-
- lightlevel1 = (float)frame / (float)maxframe;
- /* Calculate the percentage of color 1 */
-
- lightlevel2 = 1.0 - lightlevel1;
- /* Percentage of color 2 is the 100% - lightlevel1 */
-
-
- for (col2 = 0; col2 < MAXCOL; col2++)
- for (col1 = 0; col1 < MAXCOL; col1++)
- {
-
- fr = (float)pal[col1].r * lightlevel1;
- fg = (float)pal[col1].g * lightlevel1;
- fb = (float)pal[col1].b * lightlevel1;
-
- fr2= (float)pal[col2].r * lightlevel2;
- fg2= (float)pal[col2].g * lightlevel2;
- fb2= (float)pal[col2].b * lightlevel2;
-
- /* Calculate the two new colors */
-
- ir = (fr + fr2);
- ig = (fg + fg2);
- ib = (fb + fb2);
- /* Combine the percentage of color 1 with the percentage of color 2
- to form a new color */
-
- bestcolor = closest_match (ir, ig, ib, pal);
-
- fadetable[frame * (MAXCOL*MAXCOL) + col2 * MAXCOL + col1] = bestcolor;
- }
-
- }
-
- #define NUMFRAMES 10
-
- static void InitPalette(CTabHandle ctab)
- {
- WORD ptr, i;
- RGBColor color;
- UBYTE *fadetable;
-
- fadetable = new UBYTE[MAXCOL * MAXCOL * (NUMFRAMES / 2)];
-
- for (i = 0; i < NUMFRAMES/2; i++)
- {
- create_fade_table (i, NUMFRAMES, fadetable, pal);
- }
-
- for(i=0; i<256; i++)
- {
- color.red = pal[i].r * 256L;
- color.green = pal[i].g * 256L;
- color.blue = pal[i].b * 256L;
-
- (*ctab)->ctTable[i].rgb = color;
- }
- SetEntries(0, 255, (*ctab)->ctTable);
- }
-
- #define kAmbient 0.3
-
- static void MakePalette(CTabHandle ctab)
- {
- short i, j, specular, diffuse, pal_index;
- RGBColor col, color, background;
-
- color.red = 65535;
- color.green = 0;
- color.blue = 0;
-
- col.red = color.red * kAmbient;
- col.green = color.green * kAmbient;
- col.blue = color.blue * kAmbient;
-
-
- pal_index = 0;
- for(j=0; j<kDiffuse; j++)
- {
- col.red += (color.red - col.red) / (kDiffuse-j);
- col.green += (color.green - col.green) / (kDiffuse-j);
- col.blue += (color.blue - col.blue) / (kDiffuse-j);
-
- (*ctab)->ctTable[pal_index++].rgb = col;
- }
-
- color.red = 0xFFFF;
- color.green = 0xFFFF;
- color.blue = 0xFFFF;
- for(j=0; j<kSpecular; j++)
- {
- col.red += (color.red - col.red) / (kSpecular-j);
- col.green += (color.green - col.green) / (kSpecular-j);
- col.blue += (color.blue - col.blue) / (kSpecular-j);
-
- (*ctab)->ctTable[pal_index++].rgb = col;
- }
- SetEntries(0, 254, (*ctab)->ctTable);
- }
-
- void main(void)
- {
- char str[255];
- LONG TickStart, FrameCount;
-
- InitToolBox();
- load_pic();
-
- object3d object;
-
- object.importV3D("text.v3d");
-
- WindowPtr window;
- GWorldPtr gWorld;
- OSErr iErr;
- CGrafPtr savePort;
- GDHandle saveGDev;
- PixMapHandle pixBase;
- GDHandle iMainScreen;
- PixMapPtr iPixMap;
-
- window = ::GetNewCWindow(128, NULL, (WindowPtr) -1);
- ::ShowWindow(window);
- ::SetPort(window);
-
- iMainScreen = GetMainDevice();
- iPixMap = *((**iMainScreen).gdPMap);
- MakePalette(iPixMap->pmTable);
-
- rBounds = window->portRect;
- ::OffsetRect(&rBounds, -rBounds.left, -rBounds.top);
- ::SetPt(&middle, rBounds.right >> 1, rBounds.bottom >> 1);
-
- iErr = ::NewGWorld(&gWorld, 8, &rBounds, iPixMap->pmTable, NULL, keepLocal);
- if (iErr != noErr)
- {
- ::DisposeWindow(window);
- return;
- }
- pixBase = ::GetGWorldPixMap(gWorld);
- ::LockPixels(pixBase);
- ::HLockHi((Handle) pixBase);
-
- baseAddr = (**pixBase).baseAddr;
- rowBytes = (**pixBase).rowBytes & 0x1FFF;
-
- ::BackColor( whiteColor );
- ::ForeColor( blackColor );
-
- ::GetGWorld(&savePort, &saveGDev);
- ::SetGWorld(gWorld, NULL);
- ::BackColor(blackColor);
- ::ForeColor(whiteColor);
- ::SetGWorld(savePort, saveGDev);
-
- EventRecord event;
- BOOL quit = FALSE;
-
- #ifdef use_profiler
- if (::ProfilerInit(collectDetailed, bestTimeBase, 100, 10) != noErr)
- ::ExitToShell();
- #endif
- TickStart = ::TickCount();
- FrameCount = 0;
-
-
- object.applyTexture();
- object.makeRotMatrix(0, 0, 0);
- object.setGNormals();
- object.localRotate();
-
- Point curPt, oldPt;
- LONG diffPt;
- BOOL down;
-
- ::GetMouse(&curPt);
- oldPt = curPt;
- while (!quit)
- {
- GetMouse(&curPt);
- if (PtInRect(curPt, &window->portRect)) {
- if (::StillDown())
- {
- ::SetCursor(*GetCursor(iNewHandCursor));
- down = TRUE;
- } else
- {
- ::SetCursor(*GetCursor(iHandCursor));
- down = FALSE;
- }
- } else
- ::SetCursor(&qd.arrow);
-
- ::SetGWorld(gWorld, NULL);
- ::EraseRect(&rBounds);
- if (!::EqualPt(curPt, oldPt) && down)
- {
-
- if (event.modifiers & optionKey)
- {
- camera.view.z += (curPt.v - oldPt.v) * 100;
- object.localRotate();
- } else
- {
- object.makeRotMatrix(down ? curPt.v - oldPt.v : 0,
- down ? curPt.h - oldPt.h : 0, 0);
- object.setGNormals();
- object.localRotate();
- }
-
- oldPt = curPt;
-
- }
- object.display();
-
- ::sprintf(str, "fps: %.2f", (FrameCount * 60.0) / (::TickCount() - TickStart));
- ::MoveTo(10, 20);
- ::DrawText(str, 0, strlen(str));
-
- ::SetGWorld(savePort, saveGDev);
-
- ::CopyBits(*(BitMap**) gWorld->portPixMap, *(BitMap**) savePort->portPixMap,
- &rBounds, &rBounds, srcCopy, NULL);
- if (::WaitNextEvent(everyEvent, &event, 0, NULL))
- {
- if (event.what == mouseDown)
- {
- WindowPtr theWindow;
- short iWinPart;
-
- iWinPart = ::FindWindow(event.where, &theWindow);
- switch (iWinPart)
- {
- case inGoAway:
- if (::TrackGoAway(theWindow, event.where))
- quit = TRUE;
- break;
- case inContent:
- oldPt = curPt;
- break;
- }
- }
- }
- FrameCount++;
- }
- #ifdef use_profiler
- ::ProfilerDump("\pProfilerIntro.profiler");
- ::ProfilerTerm();
- #endif
- ::FlushEvents(everyEvent, 0);
-
- delete_pic();
- ::DisposeGWorld(gWorld);
- ::DisposeWindow(window);
- }
-
-